// Part.cpp: implementation of the Part class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "Part.h"
#include "PHSSHARE.h"
#include <math.h>

#include "FunctionObject.h"
#include "PersistentFacade.h"
#include "FunctionRegisterInfo.h"
#include "FunctionRegister.h"
#include "StandardGenerator.h"
#include "ModelVisitor.h"
#include "KnownPartSet.h"
#include "JointFunction.h"

using namespace PropertySystem;
using namespace PersistentObjectOperation;
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

UE_IMPLEMENT_VISITOR(PartVisitor);
UE_IMPLEMENT_DYNAMIC(Part, SupportHangerSubObject);
Part::Part()
{
	m_bIsSAAttach = FALSE;

	m_pSH = NULL;
	m_nPartIndex = ObjectNoSerialNumber;
}

Part::~Part()
{
	m_FunctionStack.RemoveAll();
	m_PropertyStack.RemoveAll();
}

Part::Part(const CString &strID)
{
	m_bIsSAAttach = FALSE;
	m_pSH = NULL;

	m_strCustomID = strID;
}

void Part::InhenceFunction()
{
//	FunctionRegisterInfo* pInfo = ::GetFunctionRegister().Get(FunctionObject::eBHCONSTRUCT);
//	FunctionObject* pObject = pInfo->CreateObject();
//	this->AttachFunction(pObject);
}

BOOL Part::CreatePartFormer(const CString& strID, const CString& strStandardID)
{
	this->m_strPartStandard = strStandardID;
//	this->m_strCustomID = strID;

	PartParameterFormerSet* pSet = ::GetPersistentFacade().GetPartParameterFormerSet();
	pSet->SetDataStandard(strStandardID);
	pSet->CreatePart(this);
	this->m_pPersistentFacade = &::GetPersistentFacade();

	InhenceFunction();

	return TRUE;
}

void Part::RegisterEffect()
{
	if(this->IsAttach())
		return;

	m_FunctionStack.RegisterEffect();
	m_PropertyStack.RegisterEffect();
}

void Part::RemoveEffect()
{
	if(this->IsAttach())
		return;
	m_FunctionStack.RemoveEffect();
	m_PropertyStack.RemoveEffect();
}
void Part::AttachFunction(FunctionObject* pFunction)
{
	ASSERT(pFunction);
	pFunction->SetOwner(this);
	m_FunctionStack.AddFunction(pFunction);
}

void Part::AddProperty(PropertySystem::PropertyVariable* pVariable)
{
	ASSERT(pVariable);
	pVariable->SetOwner(this);
	m_PropertyStack.AddProperty(pVariable);
}


void Part::RemoveProperty(const CString& strKey)
{
	delete m_PropertyStack.Remove(strKey);
}

void Part::RemoveFunction(INT nFunctionID)
{
	delete m_FunctionStack.Remove(nFunctionID);
}

const CString& Part::GetCrudeTable()
{
	CString strStandard = GetStandard();
	ASSERT(!strStandard.IsEmpty());
	Standard* pStandard = NULL;

	pStandard = ::GetPersistentFacade().GetStandardGenerator()->Generate(strStandard, pStandard);
	ASSERT(pStandard);

	return pStandard->GetCrudeDataTable();
}

BOOL Part::Accept(ModelVisitor* pVisitor)
{
	ASSERT(pVisitor);
	return pVisitor->Visit(*this);
}

BOOL Part::Accept(PersistentObjectVisitor* pVisitor)
{
	ASSERT(pVisitor);
	void* p = pVisitor->QueryInterface(PartVisitor::RuntimeClass());
	if(p != NULL)
		return ((PartVisitor*)(p))->Visit((Part*)this);
	return TRUE;
}

PartSortProperty* Part::GetPartSortProperty()
{
	ASSERT(!m_strCustomID.IsEmpty());
	ASSERT(!m_strPartStandard.IsEmpty());

	PartSortPropertySet* pSet = KnownPartSet::Instance().GetPartSortPropertySet(m_strPartStandard);
	ASSERT(pSet);

	return pSet->GetPartSortProperty(m_strCustomID);
}

void Part::SetDelete()
{
	if(this->IsDeleteState())
		return;

	PersistentObject::SetDelete();

	if(this->IsAttach())
		return;
	
	PropertyStack::Iterator* pIt = m_PropertyStack.NewPartTypeIterator();
	for(pIt->Begin(); !pIt->End(); pIt->Next())
	{
		Part* pPart = (Part*)(*pIt->Get());
		ASSERT(pPart);

		pPart->SetDelete();
	}
	delete pIt;

	JointInfo info(this);
	JointFunction* pJointFun = info.GetFirst();
	while(pJointFun != NULL)
	{
		Joint* pJoint = pJointFun->GetJoint();
		if(pJoint != NULL)
		{
			pJoint->SetDelete();
		}
		pJointFun = info.GetNext();
	}
	this->RemoveEffect();
}

void Part::SetUndoDelete()
{
	if(!this->IsDeleteState())
		return;

	PersistentObject::SetUndoDelete();

	if(this->IsAttach())
		return;

	PropertyStack::Iterator* pIt = m_PropertyStack.NewPartTypeIterator();
	for(pIt->Begin(); !pIt->End(); pIt->Next())
	{
		Part* pPart = (Part*)(*pIt->Get());
		ASSERT(pPart);

		pPart->SetUndoDelete();
	}
	delete pIt;

	JointInfo info(this);
	JointFunction* pJointFun = info.GetFirst();
	while(pJointFun != NULL)
	{
		Joint* pJoint = pJointFun->GetJoint();
		if(pJoint != NULL)
		{
			pJoint->SetUndoDelete();
		}
		pJointFun = info.GetNext();
	}
	this->RegisterEffect();
}

ModelObject* Part::Clone()
{
	ASSERT(FALSE);
	return NULL;
}

Part* Part::FindPart(INT nPartIndex)
{
	ASSERT(this->SupportHangerOwner());
	return this->SupportHangerOwner()->FindPart(nPartIndex);
}

CString Part::GetID()
{
	return this->GetPartSortProperty()->ID();
}

BOOL Part::IsAvailable()
{
	if(!ModelObject::IsAvailable())
		return FALSE;

	PropertySystem::PropertyStack::Iterator* pIt = 
		GetPropertyStack()->NewPartTypeIterator();
	ASSERT_MEMORY_VALID(pIt, FALSE);

	for(pIt->Begin(); !pIt->End(); pIt->Next())
	{
		Variable* pVar = pIt->Get();
		ASSERT(pVar);

		Part* pPart = (Part*)(*pVar);
		ASSERT(pPart);
		if(!pPart->IsAvailable())
		{
			delete pIt;
			return FALSE;
		}
	}
	delete pIt;

	return TRUE;
}

void Part::SetAvailable()
{
	ModelObject::SetAvailable();
}

void Part::SetUnavailable()
{
	ModelObject::SetUnavailable();
}